
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <chrono>
#include <sys/time.h>
#include "xcutil.h"


//int64_t get_timestamp_ms(){
//    unsigned long milliseconds_since_epoch =
//    std::chrono::duration_cast<std::chrono::milliseconds>
//        (std::chrono::system_clock::now().time_since_epoch()).count();
//    return milliseconds_since_epoch;
//}

int64_t get_timestamp_ms(){
    unsigned long milliseconds_since_epoch =
            std::chrono::duration_cast<std::chrono::milliseconds>
                    (std::chrono::system_clock::now().time_since_epoch()).count();
    return milliseconds_since_epoch;
}

int64_t get_timestamp_ms_1900() {
    int64_t seconds_1900_1970 = ( 70 * 365 + 17 ) * 86400L;
    int64_t t = get_timestamp_ms();
    return t + seconds_1900_1970 * 1000;
}

#include <iostream>
#include <sys/stat.h>

uint32_t ms_to_ntp_mid32(int64_t ms) {
    uint32_t epoch_gap_seconds = ( 70 * 365 + 17 ) * 86400L;
    uint32_t seconds = ms / 1000 + epoch_gap_seconds;
    uint64_t fractions = ms % 1000;
    fractions *= (uint64_t(1) << 32) / 1000;
    uint32_t y = seconds << 16 | ((fractions >> 16) & 0x0000FFFF);
    return y;
}

int create_udp_socket(int port){

	struct sockaddr_in addr;
	memset(&addr, 0, sizeof(struct sockaddr_in));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);

    int sock;
    if ( (sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0){
        return -1;
    }

    if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0){
        return -1;
    }
    return sock;

}


static int
write_to_file(FILE * fp, const void * data, unsigned length)
{
	const uint8_t * p = (const uint8_t *)data;
	int remains = length;
	while (remains > 0) {
		int bytes = fwrite(p, 1, remains, fp);
		if (bytes < 0) {
			printf("write file fail!!!\n");
			return -1;
		}
		p += bytes;
		remains -= bytes;
	}
	fflush(fp);
	return 0;
}

static FILE * g_fp = 0;
void xdebug_save_to_default_file(const char * file_name, const void * data, uint32_t length){
	if(!g_fp){
		g_fp = fopen(file_name, "wb");
	}
	write_to_file(g_fp, data, length);
}

void xdebug_write_to_file(void ** ctx, const char * file_name, const void * data, uint32_t length){
	FILE * fp = (FILE *) (*ctx);
	if(!fp){
		fp = fopen(file_name, "wb");
		*ctx = fp;
	}
	write_to_file(fp, data, length);
}


long long xustime(void) {
    struct timeval tv;
    long long ust;

    gettimeofday(&tv, NULL);
    ust = ((long)tv.tv_sec)*1000000;
    ust += tv.tv_usec;
    return ust;
}

long long xmstime(void) {
    struct timeval tv;
    long long mst;

    gettimeofday(&tv, NULL);
    mst = ((long long)tv.tv_sec)*1000;
    mst += tv.tv_usec/1000;
    return mst;
}

int mkdir_tree(const char *path) {
    char tmp[1024] = {0,};
    char *p = nullptr;
    snprintf(tmp, sizeof(tmp), "%s", path);
    size_t len = strlen(tmp);
    if (tmp[len - 1] == '/') {
        tmp[len - 1] = 0;
    }
    for (p = tmp + 1; *p; p++) {
        if(*p == '/') {
            *p = 0;
            mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
            *p = '/';
        }
    }
    mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
    return 0;
}